package customer_registration

import (
	"encoding/json"
	"fmt"
	"jihe.common/protos/base_server/proto"
	"jihe.common/tool"
	"strings"
	"time"
)

func (s *Model) Create(req *proto.BaseCustomerRegistration) (id string, err error) {
	intoMap := make(map[string]interface{})
	req.Id = fmt.Sprintf("%d", tool.GetSnowflakeId())
	intoMap["id"] = req.Id
	intoMap["d_uid"] = req.DUid
	if req.BodyData != nil {
		bodyDataB, err := json.Marshal(req.BodyData)
		if err != nil {
			return "", err
		}
		intoMap["body_data"] = string(bodyDataB)
	}
	if req.FashionId != "" {
		intoMap["fashion_id"] = req.FashionId
	}
	if req.Remark != "" {
		intoMap["remark"] = req.Remark
	}
	if req.Fabrics != nil {
		fabricsB, err := json.Marshal(req.Fabrics)
		if err != nil {
			return "", err
		}
		intoMap["fabrics"] = string(fabricsB)
	}
	if req.Patterns != nil {
		patternsB, err := json.Marshal(req.Patterns)
		if err != nil {
			return "", err
		}
		intoMap["patterns"] = string(patternsB)
	}
	if req.ReceivedName != "" {
		intoMap["received_name"] = req.ReceivedName
	}
	if req.ReceivedPhone != "" {
		intoMap["received_phone"] = req.ReceivedPhone
	}
	if req.ReceivedAddr != "" {
		intoMap["received_addr"] = req.ReceivedAddr
	}
	intoMap["c_uid"] = req.CUid
	intoMap["sex"] = req.Sex
	fields, vals, args := make([]string, 0), make([]interface{}, 0), make([]string, 0)
	valNum := 0
	for field, val := range intoMap {
		fields = append(fields, field)
		vals = append(vals, val)
		valNum++
		args = append(args, fmt.Sprintf("$%d", valNum))
	}
	sqlStr := fmt.Sprintf("INSERT INTO %s ("+strings.Join(fields, ",")+")VALUES("+strings.Join(args, ",")+")", s.Name)
	_, err = s.Db.Exec(sqlStr, vals...)
	if err != nil {
		return
	}
	id = req.Id
	return
}

func (s *Model) UpdateObjIsNull(id string) (err error) {
	sqlStr := fmt.Sprintf("update %s set obj_url = '' where id = $1", s.Name)
	_, err = s.Db.Exec(sqlStr, id)
	if err != nil {
		return
	}
	return
}

func (s *Model) Update(req *proto.BaseCustomerRegistration) (err error) {
	intoMap := make(map[string]interface{})

	if req.BodyData != nil {
		bodyDataB, err := json.Marshal(req.BodyData)
		if err != nil {
			return err
		}
		intoMap["body_data"] = string(bodyDataB)
	}

	if req.FashionId != "" {
		intoMap["fashion_id"] = req.FashionId
	}

	if req.Fabrics != nil {
		fabricsB, err := json.Marshal(req.Fabrics)
		if err != nil {
			return err
		}
		intoMap["fabrics"] = string(fabricsB)
	} else {
		intoMap["fabrics"] = nil
	}

	if req.Patterns != nil {
		patternsB, err := json.Marshal(req.Patterns)
		if err != nil {
			return err
		}
		intoMap["patterns"] = string(patternsB)
	} else {
		intoMap["patterns"] = nil
	}

	intoMap["remark"] = req.Remark
	intoMap["received_name"] = req.ReceivedName
	intoMap["received_phone"] = req.ReceivedPhone
	intoMap["received_addr"] = req.ReceivedAddr

	if req.ObjUrl != "" {
		intoMap["obj_url"] = req.ObjUrl
	}

	if req.Photos != nil {
		photoB, err := json.Marshal(req.Photos)
		if err != nil {
			return err
		}
		intoMap["photos"] = string(photoB)
	}

	if req.Sex != 0 {
		intoMap["sex"] = req.Sex
	}

	fields, vals := make([]string, 0), make([]interface{}, 0)
	valNum := 0
	for field, val := range intoMap {
		valNum++
		fields = append(fields, fmt.Sprintf("%s=$%d", field, valNum))
		vals = append(vals, val)
	}
	sqlStr := fmt.Sprintf("update %s set "+strings.Join(fields, ",")+" where id = '%s'", s.Name, req.Id)
	_, err = s.Db.Exec(sqlStr, vals...)
	if err != nil {
		return
	}
	return
}

func (s *Model) GetList(in *proto.BaseGetCustomerRegistrationListReq) (list []*proto.BaseCustomerRegistration, total int64, err error) {
	sqlStr := fmt.Sprintf("SELECT id, d_uid, fashion_id, c_uid, created_at, updated_at, body_data, obj_url FROM %s WHERE d_uid = '%s'", s.Name, in.DUid)
	sqlCountStr := fmt.Sprintf("SELECT COUNT(0) FROM %s WHERE d_uid = '%s'", s.Name, in.DUid)
	conditionSql := ""
	args := make([]interface{}, 0)
	if in.FashionStatus == 1 { //已选款
		conditionSql += fmt.Sprintf(" AND fashion_id != ''")
	} else if in.FashionStatus == 2 { // 未选款
		conditionSql += fmt.Sprintf(" AND fashion_id = ''")
	}
	//全部状态
	if in.BodyDataStatus == 1 { //已量体
		conditionSql += fmt.Sprintf(" AND body_data::jsonb->>'complete' = '1'")
	} else if in.BodyDataStatus == 2 { //未量体
		conditionSql += fmt.Sprintf(" AND body_data::jsonb->>'complete' is NULL")
	}
	if in.Sex != 0 {
		args = append(args, in.Sex)
		conditionSql += fmt.Sprintf(" AND sex = $%d", len(args))
	}

	_ = s.Db.QueryRow(sqlCountStr+conditionSql, args...).Scan(&total)
	args = append(args, in.PageSize)
	sqlStr = fmt.Sprintf("%s ORDER BY created_at DESC LIMIT $%d", sqlStr+conditionSql, len(args))
	args = append(args, in.Page*in.PageSize)
	sqlStr += fmt.Sprintf(" OFFSET $%d", len(args))
	rows, e := s.Db.Query(sqlStr, args...)
	if e != nil {
		err = e
		return
	}
	defer rows.Close()
	for rows.Next() {
		item := &proto.BaseCustomerRegistration{}
		var (
			createdAt *time.Time
			updatedAt *time.Time
			bodyDataB []byte
		)
		err = rows.Scan(&item.Id, &item.DUid, &item.FashionId, &item.CUid, &createdAt, &updatedAt, &bodyDataB, &item.ObjUrl)
		if err != nil {
			return
		}
		if createdAt != nil {
			item.CreatedAt = createdAt.Format("2006-01-02 15:04:05")
		}
		if updatedAt != nil {
			item.UpdatedAt = updatedAt.Format("2006-01-02 15:04:05")
		}
		json.Unmarshal(bodyDataB, &item.BodyData)
		list = append(list, item)
	}
	return
}

func (s *Model) GetDetailById(id string) (ret *proto.BaseCustomerRegistration, err error) {
	ret = new(proto.BaseCustomerRegistration)
	sqlStr := fmt.Sprintf("SELECT id, d_uid, fashion_id, c_uid, fabrics, patterns, remark, received_name, received_phone, received_addr, body_data, photos, obj_url FROM %s WHERE id = $1", s.Name)
	var (
		fabricsB  []byte
		patternsB []byte
		bodyDataB []byte
		photosB   []byte
	)
	err = s.Db.QueryRow(sqlStr, id).Scan(&ret.Id, &ret.DUid, &ret.FashionId, &ret.CUid, &fabricsB, &patternsB, &ret.Remark, &ret.ReceivedName, &ret.ReceivedPhone, &ret.ReceivedAddr, &bodyDataB, &photosB, &ret.ObjUrl)
	if err != nil {
		return
	}
	json.Unmarshal(fabricsB, &ret.Fabrics)
	json.Unmarshal(patternsB, &ret.Patterns)
	json.Unmarshal(bodyDataB, &ret.BodyData)
	json.Unmarshal(photosB, &ret.Photos)
	return
}

func (s *Model) ExistFashionId(fashionId string) (exist bool) {
	count := 0
	sqlStr := fmt.Sprintf("select count(0) from %s where fashion_id = $1 and d_uid != '1'", s.Name)
	_ = s.Db.QueryRow(sqlStr, fashionId).Scan(&count)
	return count != 0
}
